package com.xinyuan.service;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Classname AccessWork
 * @Description TODO
 * @Date 2020/6/3 9:21
 * @Created by zfl
 */
public class AccessWork {
    //接近工时表：接近和接近工时
    public Map<String, Double> singleAccessTimeMap = new HashMap<String, Double>();
    //每个包对应的接近字段
    public Map<Integer, Set<String>> accessSetMapA = new HashMap<Integer, Set<String>>();
    //A包接近工时
    public Map<Integer, Double> accessTimeMapA = new HashMap<Integer, Double>();
    //C包的接近字段
    public Map<Integer, Set<String>> accessSetMapC = new HashMap<Integer, Set<String>>();
    //C包接近工时
    public Map<Integer, Double> accessTimeMapC = new HashMap<Integer, Double>();
    //
    public Set<String> accessSetA = new HashSet<String>();
    public Set<String> accessSetC = new HashSet<String>();
    //A包总接近工时
    public Double accessTimeATotal = 0.0;
    //C包总接近工时
    public Double accessTimeCTotal = 0.0;


    private void initAccess(int maxA, double intervA, int maxC, double intervC){
        double size = maxA * 365 / intervA;
        int sizeA = (int) Math.floor(size);
        for(int i = 1; i <= sizeA; i++){
            accessSetMapA.put(i, new HashSet<String>());
        }
        for(int i = 1; i <= sizeA; i++){
            accessTimeMapA.put(i, 0.0);
        }
        size = maxC * 365 / intervC;
        int sizeC = (int) Math.floor(size);
        for(int i = 1; i <= sizeC; i++){
            accessSetMapC.put(i, new HashSet<String>());
        }
        for(int i = 1; i <= sizeC; i++){
            accessTimeMapC.put(i, 0.0);
        }
    }

    //获取表格字符串
    private String processStr(Row row, int number){
        if(row.getCell(number).getCellType() == CellType.NUMERIC){
            return String.valueOf((int)(row.getCell(number).getNumericCellValue()));
        }
        else{
            return row.getCell(number).getStringCellValue();
        }
    }

    // 根据首检和重检填入包接近 new
    private void setAccessByCheck(Set<String> access, int topCheck, int reCheck, int methodTop, int methodRe){
        if(topCheck == 0 && reCheck == 0){ }
        else{
            if(topCheck != 0){
                if(methodTop == 0){
                    if(topCheck <= accessSetMapA.size()){
                        accessSetMapA.get(topCheck).addAll(access);
                    }
                }
                else{
                    if(topCheck <= accessSetMapC.size()){
                        accessSetMapC.get(topCheck).addAll(access);
                    }
                }
            }
            if(reCheck != 0){
                if(methodRe == 0){
                    for(int i = reCheck * 2; i <= accessSetMapA.size(); i += reCheck){
                        accessSetMapA.get(i).addAll(access);
                    }
                }
                else{
                    for(int i = reCheck * 2; i <= accessSetMapC.size(); i += reCheck){
                        accessSetMapC.get(i).addAll(access);
                    }
                }
            }
        }
    }

    private Set<String> parseAccess(String check) {
        Set<String> newString = new HashSet<String>();
        Pattern r = Pattern.compile("([0-9A-Z]+)([\\s]|$)");
        Matcher m = r.matcher(check);
        while(m.find()){
            if(m.groupCount() >= 1){
                newString.add(m.group(1));
            }
        }
        return newString;
    }
    // 解析重检首检字段
    private int parseCheck(String check) {
        Pattern r = Pattern.compile("([0-9]+)[^0-9]?([AC])");
        Matcher m = r.matcher(check);
        if(m.find()){
            if(m.groupCount() >= 1){
                return Integer.parseInt(m.group(1));
            }
        }
        return -1;
    }

    // 解析类型
    private int parseMethod(String check) {
        Pattern r = Pattern.compile("([0-9]+)[^0-9]?([AC])");
        Matcher m = r.matcher(check);
        if(m.find()){
            if(m.groupCount() >= 1){
                if(m.group(2).charAt(0) == 'A') return 0;
                if(m.group(2).charAt(0) == 'C') return 1;
            }
        }
        return -1;
    }

    /*// 读取每一行，填写接近
    private void readAccessInExcel(String filePath) throws IOException {

        File file = new File(filePath);
        //Cell cell = null;
        //MTOP_ACCESS,MTOP_THRESHOL,MTOP_INTERV
        int accessNum = 0,thresholNum = 0,intervNum = 0;
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);

        Row row0 = sheet.getRow(2);
        //获取第一行的最后一个单元格的数值
        int lastCellNum=row0.getLastCellNum();
        //System.out.println(lastCellNum);
        for (int i = 0; i < lastCellNum; i++) {
            Cell cell = row0.getCell(i);
            if(cell.getStringCellValue().equalsIgnoreCase("MTOP_ACCESS")) {
                accessNum = i;
            }else if(cell.getStringCellValue().equalsIgnoreCase("MTOP_THRESHOL")) {
                thresholNum = i;
            }else if(cell.getStringCellValue().equalsIgnoreCase("MTOP_INTERV")){
                intervNum = i;
            }
        }

        for(int i = 3; i <= sheet.getLastRowNum(); i++){
            //i行的接近、首检、重检
            Row row1 = sheet.getRow(i);
            Set<String> access = new HashSet<String>();
            Cell cellAccess = row1.getCell(accessNum);
            if(row1.getCell(accessNum) != null){
                //access = parseAccess(row1.getCell(accessNum).getStringCellValue());
                switch (cellAccess.getCellType()) {
                    case FORMULA:
                        access = parseAccess(cellAccess.getCellFormula());
                        break;
                    case NUMERIC:
                        access = parseAccess(String.valueOf(cellAccess.getNumericCellValue()));
                        break;
                    case STRING:
                        access = parseAccess(cellAccess.getStringCellValue());
                        break;
                    default:
                        break;
                }
            }
            int topCheck = parseCheck(row1.getCell(thresholNum).getStringCellValue());
            int reCheck = parseCheck(row1.getCell(intervNum).getStringCellValue());
            int method = parseMethod(row1.getCell(thresholNum).getStringCellValue());
            if(method == 0){//A检
                setAccessByCheck(access, topCheck, reCheck, accessSetMapA);
            }
            else{//C检
                setAccessByCheck(access, topCheck, reCheck, accessSetMapC);
            }
        }
        workbook.close();
        stream.close();
    }*/
    // 读取每一行，填写接近
    private void readAccessInExcel(String filePath) throws IOException {

        File file = new File(filePath);
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);

        for(int i = 3; i < sheet.getLastRowNum(); i++){
            Row row = sheet.getRow(i);

            Set<String> access = new HashSet<String>();
            if(row.getCell(10) != null){
                access = parseAccess(processStr(row, 10));
            }

            int topCheck = parseCheck(row.getCell(21).getStringCellValue());
            int reCheck = parseCheck(row.getCell(23).getStringCellValue());
            int methodTop = parseMethod(row.getCell(21).getStringCellValue());
            int methodRe = parseMethod(row.getCell(23).getStringCellValue());
            setAccessByCheck(access, topCheck, reCheck, methodTop, methodRe);
        }
        workbook.close();
        stream.close();
    }

   /* //缓存接近工时表
    private void initSingleTimeInExcel(String filePath) throws IOException{
        File file = new File(filePath);
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);
        for(int i = 1; i < sheet.getLastRowNum(); i++){
            Row row = sheet.getRow(i);
            Cell cellAccessName = row.getCell(0);
            String accessName = null;
            switch (cellAccessName.getCellType()) {
                case FORMULA:
                    accessName = cellAccessName.getCellFormula();
                    break;
                case NUMERIC:
                    accessName  = String.valueOf(cellAccessName.getNumericCellValue());
                    break;
                case STRING:
                    accessName = cellAccessName.getStringCellValue();
                    break;
                default:
                    break;
            }
            Double time = row.getCell(2).getNumericCellValue() * row.getCell(3).getNumericCellValue();
            singleAccessTimeMap.put(accessName, time);
        }
        workbook.close();
        stream.close();
    }*/

    //缓存接近工时表
    private void initSingleTimeInExcel(String filePath) throws IOException{
        File file = new File(filePath);
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);
        for(int i = 1; i < sheet.getLastRowNum(); i++){
            Row row = sheet.getRow(i);
            String accessName = processStr(row, 0);
            Double time = row.getCell(2).getNumericCellValue() * row.getCell(3).getNumericCellValue();
            singleAccessTimeMap.put(accessName, time);
        }
        workbook.close();
        stream.close();
    }

    //填写接近
    private void fillAccessTimeMap(){
        for(int i = 1; i <= accessSetMapA.size(); i++){
            for(String a : accessSetMapA.get(i)){
                if(singleAccessTimeMap.get(a) != null){
                    accessTimeMapA.put(i, accessTimeMapA.get(i) + singleAccessTimeMap.get(a));
                }
            }
        }

        for(int i = 1; i <= accessSetMapC.size(); i++){
            for(String a : accessSetMapC.get(i)){
                //判断access字段是否存在
                if(singleAccessTimeMap.get(a) != null){
                    accessTimeMapC.put(i, accessTimeMapC.get(i) + singleAccessTimeMap.get(a));
                }
            }
        }
    }

    //计算总接近
    private void addAllAccess() {
        for (int i = 1; i <= accessSetMapA.size(); i++) {
            accessSetA.addAll(accessSetMapA.get(i));
        }
        for (int i = 1; i <= accessSetMapC.size(); i++) {
            accessSetC.addAll(accessSetMapC.get(i));
        }
        for (String a : accessSetA) {
            if (singleAccessTimeMap.get(a) != null) {
                accessTimeATotal += singleAccessTimeMap.get(a);
            }
        }
        for (String a : accessSetC) {
            if (singleAccessTimeMap.get(a) != null) {
                accessTimeCTotal += singleAccessTimeMap.get(a);
            }
        }
    }
    //封装好的计算
    public void calculateAll(String MTOP, String Access, int maxA, double intervA, int maxC, double intervC) throws IOException{
        initAccess(maxA, intervA, maxC, intervC);
        readAccessInExcel(MTOP);
        initSingleTimeInExcel(Access);
        fillAccessTimeMap();
        addAllAccess();
        /*for (Set<String> s : accessSetMapA.values()) {
            for(String str : s){
                System.out.println(str);
            }
            System.out.println("------");
        }*/
    }
}